#获取数据
from sklearn.datasets import fetch_lfw_people
import matplotlib.pyplot as plt
faces = fetch_lfw_people(min_faces_per_person=60)
x,y = faces.data,faces.target
target_names=faces.target_names
n_samples,h,w=faces.images.shape
print(target_names)
print(n_samples,h,w)

#数据降维处理
from sklearn.decomposition import PCA
n_components=150
pca=PCA(n_components=n_components,svd_solver='randomized',whiten=True,random_state=70).fit(x)
eigenfaces=pca.components_.reshape((n_components,h,w))
x_pca=pca.transform(x)
fig,ax=plt.subplot(3,5)
for i,axi in enumerate(ax.flat):
    axi.imshow(eigenfaces[i].reshape(h,w),cmap='bone')
    axi.set(xticks=[],yticks=[])
plt.show

#训练与评估模型
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split
import numpy as np
# 拆分数据集
x_train, x_test, y_train, y_test = train_test_split(x_pca, y, test_size=0.40, random_state=42)
# 使用网格搜索法寻找参数的最优值
param_grid = {
    'C': [1, 5, 10, 50, 100],
    'gamma': [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1]
}
grid = GridSearchCV(SVC(kernel="rbf", random_state=0),param_grid=param_grid, cv=5)
grid.fit(x_train, y_train)

print("最优参数值为: %s" % grid.best_params_)
# 最优模型评估
model = grid.best_estimator_  # 获取最优模型
pred = model.predict(x_test)
re = classification_report(y_test, pred, target_names=faces.target_names)

print("最优模型的评估报告：")
print(re)

#最终输出图像
fig, ax = plt.subplots(4, 6)
for i, axi in enumerate(ax.flat):
    # 绘制图像
    axi.imshow(eigenfaces[i].reshape(h, w), cmap='bone')
    axi.set(xticks=[], yticks=[])
    
    # 设置边框样式
    box = dict(fc='black', alpha=0.4)
    
    # 显示预测姓名，预测正确显示为黑色文字，预测错误显示为黑色加边框文字
    axi.set_ylabel(faces.target_names[pred[i]].split()[-1], bbox=None if pred[i]==y_test[i] else box)

# 设置字体和标题
plt.rcParams['font.sans-serif'] = 'Simhei'
plt.suptitle('预测名人的姓名（加边框的名字表示预测错误）', size=10)
plt.show()